<?php

namespace App\Services;


use Config;
use Mockery\Exception;

class SendSms {


    /**
     * 服务器地址
     * @var string
     */
    protected $curl_url = 'http://111.13.19.27/smsbill/mt';

    /**
     * 端口
     * @var string
     */
    protected $port = 80;

    /**
     * 企业签名
     * @var string
     */
    protected $signature = '';

    /**
     * 用户ID
     * @var string
     */
    protected $userId = '141600201';
    /**
     * 密码（加密过的）
     * @var string
     */
    protected $password = '5B04B6DE58D5FE0C4A94BDC0B129AB41';

    /**
     * 模板id
     * @var string
     */
    protected $templateId = '141600201_001';

    /**
     * 接口请求方式
     * @var string
     */
    protected $httpMethod = 'POST';

    /**
     * 字符编码
     * @var string
     */
    protected $charSet = 'UTF-8';


    /**
     * 参数数组
     * @var array
     */
    protected $params = [];

    /**
     * 接口类型，mt，必须填写
     * @var array
     */
    protected $Cmd = 'mt';

    /**
     * 鉴权令牌
     * @var array
     */
    protected $authorization = '';


    /** 设置参数
     * @param $key
     * @param $value
     */
    public function setParam($key,$value){
        $this->params[$key] = $value;
    }

    public function sendMsg($phone,$content,$templateId,$signature){

        $this->setParam('TS',strval(time()));       //Timestamp, 自1970-01-01 00:00:00以来的秒数，long类型，必须填写
        $this->setParam('phone',$phone);
        $this->setParam('content',$content);

        if(!empty($templateId)){
            $this->templateId = $templateId;
        }

        if(!empty($signature)){
            $this->signature = $signature;
        }

        return $this->makeRequest();

    }//end func sendMsg

    /**
     * 发送注册短信
     * @param $phone
     * @param $code
     * @return mixed|string
     */
    public function regMsg($phone, $content, $templateId='', $signature=''){

        return $this->sendMsg($phone, $content, $templateId, $signature);

    }

    public function massMsg($phone, $command, $templateId='', $signature=''){

        return $this->sendMsg($phone, $command, $templateId, $signature);
    }


    private function makeRequest(){

        $returnData = ['status'=>9999, 'message'=>'', 'data'=>'' ];

        $phones = $this->phoneNumberConstraint($this->params['phone']);
        $content = $this->contentConstraint($this->params['content']);

        //要post的数据
        $post_data = $this->postData($phones, $content);

        //请根据实际值替换下面的变量
        $xmlData = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><request><userId>$this->userId</userId><password>"
            .$this->password
            . "</password><templateId>$this->templateId</templateId><phone>$phones</phone><port>00201</port>"
            . "<data>$content</data><signature></signature></request>";

        $this->authorization = $this->authorization($xmlData);

        $headerArr = $this->getHeader();        //header信息

        try {
            $ch = curl_init();

            curl_setopt($ch, CURLOPT_URL, $this->curl_url);

            // post数据
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//不直接输出，返回到变量

            // post的变量
            curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);

            //设置header
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArr);

            //发送xml格式的数据
            curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlData);

            $curl_result = curl_exec($ch);

            curl_close($ch);

        }catch (Exception $e){

            $curl_result = 3010;

        }

        switch($curl_result){

            case '<?xml version="1.0" encoding="UTF-8"?><response><retCode>1000</retCode></response>':
                $returnData['status'] = 1000;
                $returnData['message'] = '成功';
                break;
            case '<?xml version="1.0" encoding="UTF-8"?><response><retCode>3001</retCode></response>':
                $returnData['status'] = 3001;
                $returnData['message'] = '请求格式错误';
                break;
            case '<?xml version="1.0" encoding="UTF-8"?><response><retCode>3002</retCode></response>':
                $returnData['status'] = 3002;
                $returnData['message'] = '用户名或密码不正确';
                break;
            case '<?xml version="1.0" encoding="UTF-8"?><response><retCode>3003</retCode></response>':
                $returnData['status'] = 3003;
                $returnData['message'] = '模板 id不存在';
                break;
            case '<?xml version="1.0" encoding="UTF-8"?><response><retCode>3004</retCode></response>':
                $returnData['status'] = 3004;
                $returnData['message'] = '变量数据与模板不匹配';
                break;
            case '<?xml version="1.0" encoding="UTF-8"?><response><retCode>3005</retCode></response>':
                $returnData['status'] = 3005;
                $returnData['message'] = '超过50个变量标签';
                break;
            case '<?xml version="1.0" encoding="UTF-8"?><response><retCode>3006</retCode></response>':
                $returnData['status'] = 3006;
                $returnData['message'] = '扩展端口错误';
                break;
            case '<?xml version="1.0" encoding="UTF-8"?><response><retCode>3007</retCode></response>':
                $returnData['status'] = 3007;
                $returnData['message'] = '号码超过了1000个数量限制';
                break;
            case '<?xml version="1.0" encoding="UTF-8"?><response><retCode>3008</retCode></response>':
                $returnData['status'] = 3008;
                $returnData['message'] = '无合法手机号';
                break;
            case '<?xml version="1.0" encoding="UTF-8"?><response><retCode>3009</retCode></response>':
                $returnData['status'] = 3009;
                $returnData['message'] = '令牌错误';
                break;
            case '<?xml version="1.0" encoding="UTF-8"?><response><retCode>3010</retCode></response>':
                $returnData['status'] = 3010;
                $returnData['message'] = '客户端请求失败';
                break;
            case '<?xml version="1.0" encoding="UTF-8"?><response><retCode>9999</retCode></response>':
                $returnData['status'] = 9999;
                $returnData['message'] = '其他错误';
                break;
            default:
                $returnData['status'] = 0;
                $returnData['message'] = $curl_result;
                break;
        }//end switch

        return $returnData;

    }//end func makeRequest


    /*
     * 鉴权令牌
     * 算法为：MD5(XML内容+TS+密码)。即把XML内容字符串、TS字符串和请求password字段已加密字符串串联起来后再计算MD5，并且统一转换成大写字母
     *
     * @param xml $xmlData
     * @return string
     *
     */
    private function authorization($xmlData){

        return $authorization = strtoupper(md5($xmlData.$this->params['TS'].$this->password));

    }//end func authorization


    /*
     * 要发送的头信息
     *
     * @param xml $xmlData
     * @return string
     *
     */
    private function getHeader(){

        $header = array(
            'Content-Type'=>'text/xml;charset=utf-8',
            'Cmd'=>$this->Cmd,
            'TS'=>$this->params['TS'],
            'Authorization'=>$this->authorization,
            'Connection'=>'Keep-AliveConnection: Keep-Alive'
        );

        $headerArr = array();
        foreach($header as $n => $v ) {

            $headerArr[] = $n .':' . $v;

        }//end foreach()

        return $headerArr;
    }//end func getHeader


    /*
     * 要post的数据
     *
     * @param string $phones
     * @param string $content
     * @return string
     *
     */
    private function postData($phones, $content){

        $post_data = array (
            "userId" => $this->userId,
            "password" => $this->password,
            "templateId" => $this->templateId,
            "phone" => $phones,
            "port" => $this->port,
            "data" => "<![CDATA[$content]]>",
            "signature" => $this->signature
        );

        return $post_data;
    }//end func postData

    /**
     * 手机号码约束
     * @param int phoneNumbers 接收短信的手机号码数组
     * @return mixed
     */
    public function phoneNumberConstraint($phoneNumbers){
        //约束： 接口中定义的手机号码，必须为11位手机号码，不能包含+86等前缀。多个手机号码用逗号（，）分隔。

        $returnData = ['status'=>1, 'message'=>'', 'data'=>'' ];

        if(empty($phoneNumbers)){

            $returnData['status'] = 0;

            $returnData['message'] = '手机号码数组不能为空';

            return $returnData;

        }//end if()


        /*
        $phone = '';
        foreach ($phoneNumbers as $key=>$phoneNumber) {

            if($key==0){

                $phone = $phoneNumber;

            }else{

                $phone .= ','.$phoneNumber;

            }//end if()

        }//end foreach()*/

        $returnData['data'] = $phoneNumbers;

        return $returnData['data'];

    }//end func phoneNumberConstraint

    /**
     * 短信内容约束
     * @param int content 短信内容
     * @return mixed
     */
    public function contentConstraint($content){
        //约束： 变量数据使用竖线（|）分隔，变量内容不能包含竖线，否则内容会被拆分成2个变量数据。
        //如果字段值中包含特殊字符（&, <, >, ‘, “）需要进行转义处理

        $returnData = ['status'=>1, 'message'=>'', 'data'=>'' ];

        if(empty($content)){

            $returnData['status'] = 0;

            $returnData['message'] = '要发送的内容参数不能为空';

            return $returnData;

        }//end if()

        /*
        $data = '';
        foreach ($content as $key=>$param) {

            if($key==0){

                $data = '<![CDATA['.$param.']]>';
                //$data = $param;

            }else{

                //$data .= '|'.$param;
                $data .= '<![CDATA['.$param.']]>';

            }//end if()

        }//end foreach()*/

        $returnData['data'] = htmlspecialchars($content);

        return $returnData['data'];
    }//end func contentConstraint


}